import os
import MySQLdb
import logging
from time import time
from datetime import datetime

from mysql_wrapper import MySQLWrapper
from Gmetad.gmetad_plugin import GmetadPlugin
from Gmetad.gmetad_config import getConfig, GmetadConfig
from Gmetad.gmetad_element import Element

def get_plugin():
    ''' All plugins are required to implement this method.  It is used as the factory
        function that instanciates a new plugin instance. '''
    # The plugin configuration ID that is passed in must match the section name
    #  in the configuration file.
    return MySQLPlugin('mysql')

def changebrace(str):
  return '('+str[1:-1]+')'

def removequote(str):
  return str.replace('\'','')

class MySQLPlugin(GmetadPlugin):
    ''' This class implements the RRD plugin that stores metric data to RRD files.'''

    MySQLDB = 'MySQLDatabase'
    MySQLHost = 'MySQLHost'
    MySQLUser = 'MySQLUser'
    MySQLPassword = 'MySQLPassword'
    MySQLTable = 'MySQLTable' 

    # Default RRAs
    _cfgDefaults = {
            MySQLDB : 'ganglia',
            MySQLHost : 'localhost',
            MySQLUser : 'ganglia',
            MySQLPassword : 'ganglia',
            MySQLTable : 'kmonitor' 
    }

    # Default Schema
    MetricSchema = '\
      time TIMESTAMP,\
      host char(48),\
      name char(64),\
      value char(32),\
      type  char(8),\
      attr  varchar(128)'


    def __init__(self, cfgid):
        self.cfg = None
        self._resetConfig()

        # The call to the parent class __init__ must be last
        GmetadPlugin.__init__(self, cfgid)
        self.InitMySQLConn()

    def _resetConfig(self):
        self.cfg = MySQLPlugin._cfgDefaults

    def _parseConfig(self, cfgdata):
        '''This method overrides the plugin base class method.  It is used to
            parse the plugin specific configuration directives.'''
        for kw,args in cfgdata:
          if self._cfgDefaults.has_key(kw):
            self.cfg[kw] = args

    def InitMySQLConn(self):
        self.mysql = MySQLWrapper()
        self.mysql.setParam(self.cfg[MySQLPlugin.MySQLHost],
                            self.cfg[MySQLPlugin.MySQLUser],
                            self.cfg[MySQLPlugin.MySQLPassword],
                            self.cfg[MySQLPlugin.MySQLDB])
        self.table = self.cfg[MySQLPlugin.MySQLTable]

    '''
    def _checkMetric(self, cluster, host, metricNode):
        metric = metricNode.getAttr('name')
        if not self.mysql.existItemPred(MetaTable,
              'cluster=\'%s\' and host=\'%s\''
              %(cluster, host)) :
          self.mysql.create('%s.%s'%(cluster, host),
                            '(metric varchar(64), /
                            time Date, /
                            value varchar(64))')
    '''


    def _updateMetric(self, clusterNode, metricNode):
        ''' This method updates an MySQL file with current metric values. '''
        # If the node has a time stamp then use it to update the MySQL.  Otherwise get
        #  the current timestamp.
#        metric['attr'] = metricNode.getAttr('attr') 


    def start(self):
        '''Called by the engine during initialization to get the plugin going.'''
        logging.debug("MySQL start called")
        self.mysql.connect()
        if not self.mysql.checkTable(self.table):
          self.mysql.create(self.table, MySQLPlugin.MetricSchema) 

    def stop(self):
        '''Called by the engine during shutdown to allow the plugin to shutdown.'''
        logging.debug("MySQL stop called")
        self.mysql.disconnect()

    def notify(self, clusterNode):
        '''Called by the engine when the internal data source has changed.'''
        # Get the current configuration
	gmetadConfig = getConfig()
        # Find the data source configuration entry that matches the cluster name
        
        for ds in gmetadConfig[GmetadConfig.DATA_SOURCE]:
            if ds.name == clusterNode.getAttr('name'):
                break
        if ds is None:
            logging.info('No matching data source for %s'%clusterNode.getAttr('name'))
            return
        
        try:
            if clusterNode.getAttr('status') == 'down':
                return
        except AttributeError:
            pass

        colnames = '(time, host, name, value, type, attr)'
        values = '';
        first = True;
          
        clustertime = clusterNode.getAttr('localtime')
        if clustertime is None:
            processTime = strftime("%Y-%m-%d %H:%M:%S")
	else:
	    processTime = \
	      datetime.fromtimestamp(float(clustertime)).strftime("%Y-%m-%d %H:%M:%S")

        for hostNode in clusterNode:
            for metricNode in hostNode:
                if metricNode.getAttr('type') in ['string', 'timestamp']:
                    continue
                value = '(\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\')'%(\
                        str(processTime),\
                        clusterNode.getAttr('name')+'.'+hostNode.getAttr('name'),\
                        metricNode.getAttr('name'),\
                        metricNode.getAttr('val'),\
                        metricNode.getAttr('type'),\
                        '')
                if not first:
                  values = values + ',' + value
                else:
                  values = value;
                first = False;

        self.mysql.insert(self.table,
                          colnames,
                          values)


if __name__ == '__main__':
  sql = get_plugin()
  attrs = {'name' : 'compute cluster',
           'status' : 'up'}
  clusterNode = Element('cluster', attrs)

  attrs = {'name' : 'host1'}
  hostNode = Element('host', attrs)

  attrs = {'name' : 'cpu',
           'val'  : '123',
           'type' : 'int'}
  metricNode = Element('metric', attrs)

  clusterNode.children[str(hostNode)] = hostNode
  hostNode.children[str(metricNode)] = metricNode

  sql.start()
  sql.notify(clusterNode) 
  sql.stop()
